import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common";
import { Reflector } from "@nestjs/core";
import { Observable } from "rxjs";
import { IS_PUBLIC_KEY } from "./public.decorator";
import { JwtService } from "@nestjs/jwt";
import { JWT_SECRET_KEY } from "./auth.jwt.secrect";

@Injectable()
export class AuthGuard implements CanActivate {
  // 引入 jwt 服务，验证 token 是否失效
  constructor(private jwtService: JwtService, private reflector: Reflector) {}
  async canActivate(context: ExecutionContext): Promise<boolean> {
    // 获取请求上下文判断当前接口是否是公开的
    const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ])
    if(isPublic) return true
    // 获取接口请求信息
    const request = context.switchToHttp().getRequest()
    // console.log("🚀 ~ AuthGuard ~ canActivate ~ request:", request.headers)
    const token = extractTokenFormHeader(request)
    // console.log("🚀 ~ AuthGuard ~ canActivate ~ token:", token)
    // 判断token是否存在
    if(!token) {
      // 不存在则直接报错返回提示
      throw new UnauthorizedException("token不存在")
    }
    // 验证token是否有效
    try {
      // 解析token，获取payload
      const payload = await this.jwtService.verifyAsync(token, {
        secret: JWT_SECRET_KEY
      })
      // console.log("🚀 ~ AuthGuard ~ canActivate ~ payload:", payload)
      // 将payload信息挂载到request上
      request['user'] = payload
      // console.log("🚀 ~ AuthGuard ~ canActivate ~ request:", request)
    } catch (error) {
      // console.log("🚀 ~ AuthGuard ~ canActivate ~ error:", error)
      throw new UnauthorizedException("token失效")
    }
    return true
  }
}

// 解析request信息
const extractTokenFormHeader = (request: any) => {
  const [type, token] = request.headers.authorization?.split(" ") ?? []
  return type === 'Bearer' ? token : ''
}
